﻿// ## 2023/10/27 # 铃 # 完全汉化 ##
// ## 2022/04/14 # 江东新风 # 玩家军团在设定禁止运输时不再触发脚本 ##
// ## 2022/02/14 # 江东新风 # 部分常量中文化 ##
// ## 2020/07/26 ##
/*
	@제작 : masterpiecek
	@내용 : 对先前AI势力在各主要地区城市之間物資运输不暢的地方进行改进기존 AI세력의 전방지역 도시들 간에 물자 运输이 원활하게 이루어지지 않던 부분을 개선
*/

namespace AI城市物资运输
{

	//============================================ < 用户设置 > ============================================

	/// [ 运输基本条件设置 ]

	// 城市操作主体的功能应用设置
	const array<bool> AI_城市物资运输_应用 = {/*玩家委任军团*/ true, /*电脑*/ true};

	// 当前剧本的经过月数小于基准值时不进行运输
	const int 运输基本条件_经过月数 = 6;

	// 势力的城市数量小于基准值时不进行运输
	const int 运输基本条件_势力城市数 = 3;

	///

	//-------------------------------------------------------------------------------------------------------

	/// [ 运输可行条件设置 ]：运输部队出发城市的条件

	// 如果距离运输部队出发城市的基准距离范围内存在

	const array<bool> 运输可行条件_敌部队条件_应用 = {/*玩家委任军团*/ true, /*电脑*/ true};
	const int 运输可行条件_基准敌部队距离 = 12;
	const int 运输可行条件_基准敌部队数 = 2;
	const int 运输可行条件_基准敌部队兵力 = 4000;

	// 运输部队出发城市的当前兵力与最大兵力的比例（%）低于基准值时排除
	const array<bool> 运输可行条件_兵力条件_应用 = {/*玩家委任军团*/ true, /*电脑*/ true};
	const array<int> 运输可行条件_兵力条件_比例 = {/*玩家委任军团*/ 50, /*电脑*/ 50};

	// 运输部队出发城市的当前兵力与当前载重量的比例（%）低于基准值时排除
	const array<bool> 运输可行条件_兵量条件_应用 = {/*玩家委任军团*/ true, /*电脑*/ true};
	const array<int> 运输可行条件_兵量条件_比例 = {/*玩家委任军团*/ 150, /*电脑*/ 150};

	/// -------------------------------------------------------------------------------------------------------
	/// [ 运输需求条件设置 ]：接收运输的城市的条件

	// 如果距离接收运输的城市的基准距离范围内存在敌军部队，则判断敌军部队数量和敌军士兵数量是否达到基准值以上，若是则不接收运输

	const array<bool> 运输需求条件_敌部队条件_应用 = {/*玩家委任军团*/ true, /*电脑*/ true};
	const int 运输需求条件_基准敌部队距离 = 12;
	const int 运输需求条件_基准敌部队数 = 3;
	const int 运输需求条件_基准敌部队兵力 = 6000;

	// 接收运输的城市的当前兵力与最大兵力的比例超过基准值时不接收运输
	const array<bool> 运输需求条件_兵力条件1_应用 = {/*玩家委任军团*/ true, /*电脑*/ true};
	const array<int> 运输需求条件_兵力条件1_比例 = {/*玩家委任军团*/ 50, /*电脑*/ 50};

	// 运输部队出发城市的当前兵力与接收运输的城市的当前兵力的比例超过基准值时不接收运输
	const array<bool> 运输需求条件_兵力条件2_应用 = {/*玩家委任军团*/ true, /*电脑*/ true};
	const array<int> 运输需求条件_兵力条件2_比例 = {/*玩家委任军团*/ 50, /*电脑*/ 50};

	// 如果接收运输的城市发生或即将发生瘟疫灾害，则不接收运输（是否应用于前方城市状态的条件设置）
	const array<bool> 运输需求条件_瘟疫条件_应用 = {/*玩家委任军团*/ true, /*电脑*/ true};
	const array<bool> 瘟疫条件_前方城市_应用排除 = {/*玩家委任军团*/ true, /*电脑*/ true};

	// 如果接收运输的城市发生或即将发生蝗灾，则不接收运输（是否应用于前方城市状态的条件设置）
	const array<bool> 运输需求条件_蝗灾条件_应用 = {/*玩家委任军团*/ true, /*电脑*/ true};
	const array<bool> 蝗灾条件_前方城市_应用排除 = {/*玩家委任军团*/ true, /*电脑*/ true};

	/// -------------------------------------------------------------------------------------------------------

	/// [运输部队相关设置]

	// 在确定运输部队的领导者时，排除忠诚度低于标准忠诚度的武将
	const int 运输部队_领导候选_标准忠诚度 = 85;

	// 在确定运输部队的领导者时，是否将具有运输特技的武将设为首要条件
	const bool 运输部队领导_运输特技_反映 = true;

	// 在确定运输部队的领导者时，对候选武将中能力值最高的武将进行优先选择的武将能力设置
	const int 运输部队领导_应用能力 = 武将能力_政治;

	// 运输部队在前往城市时的各项运输比例（%）设置
	const array<int> 运输比例_金 = {/*玩家委任军团*/ 50, /*电脑*/ 50};
	const array<int> 运输比例_兵力 = {/*玩家委任军团*/ 50, /*电脑*/ 50};
	const array<int> 运输比例_兵粮 = {/*玩家委任军团*/ 50, /*电脑*/ 50};
	const array<int> 运输比例_兵装 = {/*玩家委任军团*/ 50, /*电脑*/ 50};
	const array<int> 运输比例_攻具 = {/*玩家委任军团*/ 50, /*电脑*/ 50};
	const array<int> 运输比例_船 = {/*玩家委任军团*/ 50, /*电脑*/ 50};

	// 当运输部队前往的城市处于前方状态时，各项运输项目的最低维持量设置
	const array<int> 最低维持量_金 = {/*玩家委任军团*/ 2000, /*电脑*/ 2000};
	const array<int> 最低维持量_兵力 = {/*玩家委任军团*/ 20000, /*电脑*/ 20000};
	const array<int> 最低维持量_兵粮 = {/*玩家委任军团*/ 80000, /*电脑*/ 80000};
	const array<int> 最低维持量_兵装 = {/*玩家委任军团*/ 10000, /*电脑*/ 10000};
	const array<int> 最低维持量_攻具 = {/*玩家委任军团*/ 3, /*电脑*/ 3};
	const array<int> 最低维持量_船 = {/*玩家委任军团*/ 3, /*电脑*/ 3};

	// 当运输部队出发的城市处于边界状态时，设置运输项目的最低保持量
	const array<int> 最低维持量_边界_金 = {/*玩家委任军团*/ 2000, /*电脑*/ 2000};
	const array<int> 最低维持量_边界_兵力 = {/*玩家委任军团*/ 10000, /*电脑*/ 10000};
	const array<int> 最低维持量_边界_兵粮 = {/*玩家委任军团*/ 40000, /*电脑*/ 40000};
	const array<int> 最低维持量_边界_兵装 = {/*玩家委任军团*/ 5000, /*电脑*/ 5000};
	const array<int> 最低维持量_边界_攻具 = {/*玩家委任军团*/ 0, /*电脑*/ 0};
	const array<int> 最低维持量_边界_船 = {/*玩家委任军团*/ 0, /*电脑*/ 0};

	/// =======================================================================================================

	const int 城市状态_后方 = 0, 城市状态_边界 = 1, 城市状态_前线 = 2;

	class Main
	{

		///	<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

		// 用于AI脚本函数链的前一个处理程序句柄保存
		pk::func261_t @prev_callback_261;

		/**
			[添加考虑因素]

			如果特定关卡或港口包含在运输部队的移动路径中，并且是敌方据点，则受到限制
			(取决于地形的可移动设置)
		*/

		///	<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

		Main()
		{
			@prev_callback_261 = cast<pk::func261_t @>(pk::get_func(261));
			pk::reset_func(261);
			pk::set_func(261, pk::func261_t(func261));
		}

		///	<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

		/**
		@param  force : AI 势力
		@return

		@return如果是自己处理的，那就是true。 如果想交给电脑，就false。
		*/
		// 注意:如果使用AI脚本函数(261)，玩家1军团已被排除
		// 注意:261函数是整个AI脚本，因此必须在运输部队出阵后无条件关闭上一个hander
		bool func261(pk::force @force)
		{
			supplies_transport_of_AI_city(force);

			if (prev_callback_261 is null)
				return false;
			return prev_callback_261(force);
		}

		void supplies_transport_of_AI_city(pk::force @force)
		{
			// 确认事件发生的基本条件:经过月数，势力城市数等
			int controller_index = get_controller_index(force);
			if (!是否满足运输基本条件(force, controller_index))
				return;

			for (int city_id = 0; city_id < 城市_末; city_id++)
			{
				pk::city @city = pk::get_city(city_id);
				if (!pk::is_alive(city))
					continue;
				if (city.get_force_id() != force.get_id())
					continue;

				// 基本条件://玩家1军团城市除外
				if (pk::is_player_controlled(city))
					continue;

				// 加入排除玩家军团的判断
				if (pk::get_force(city.get_force_id()).is_player())
				{
					auto district = pk::get_district(city.get_district_id());
					if (!district.transport)
						continue;
				}

				// 确认运输部队是否可以运输进城的城市的条件。
				pk::building @building = pk::city_to_building(city);
				if (!运输是否满足条件(city, building, controller_index))
					continue;

				// 在运输部队即将出阵的城市自势力邻近城市中搜索运输候选城市
				array<pk::city @> neighbor_city_arr = 搜索城市_候选(city, controller_index);
				if (int(neighbor_city_arr.length) == 0)
					continue;

				// 运输候选城市的优先顺序。
				neighbor_city_arr.sort(function(a, b) { return main.比较优先级(a, b); });
				pk::city @neighbor_city = neighbor_city_arr[0];
				if (!pk::is_alive(neighbor_city))
					continue;

				// 运输部队从将要进军的城市转移到将要进军的城市
				pk::building @neighbor_building = pk::city_to_building(neighbor_city);
				运输部队出发(city, building, neighbor_building, controller_index);
			}
		}

		///	<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

		// 检查运输基本条件是否满足以触发事件
		bool 是否满足运输基本条件(pk::force @force, int controller_index)
		{
			// 基本条件：检查是否为普通游戏（不是决战、教程或任务进行中）
			if (!is_normal_game())
				return false;
			// 基本条件：检查是否为普通势力（排除敌对势力）
			if (!pk::is_normal_force(force))
				return false;

			// 设置条件：检查城市物资运输是否应用
			if (!AI_城市物资运输_应用[controller_index])
				return false;

			// 设置条件：当前剧本经过的月数是否低于基准值，如果是则不运输
			if (pk::get_elapsed_months() < 运输基本条件_经过月数)
				return false;

			// 设置条件：势力的城市数是否低于基准值，如果是则不运输
			if (pk::get_city_count(force) < 运输基本条件_势力城市数)
				return false;

			return true;
		}

		// 检查运输队触发的城市是否满足条件
		bool 运输是否满足条件(pk::city @city, pk::building @building, int controller_index)
		{
			// 基本条件：排除运输队触发的城市状态为后方（没有敌对城市在2个城市距离内的情况）
			int city_status = get_city_status(city);
			if (city_status == 城市状态_后方)
				return false;

			// 基本条件：排除城市中没有可行动的武装
			if (pk::get_idle_person_list(building).count == 0)
				return false;

			// 基本条件：排除城市的行动力不足以执行运输命令
			/// 注意：运输命令消耗的行动力为10
			if (!ap_is_enough(city, 10, 设施_军事府))
				return false;

			// 设置条件：如果运输队触发的城市周围一定距离范围内存在一定数量的敌对部队和敌对兵力，则排除
			if (运输可行条件_敌部队条件_应用[controller_index])
			{
				int enemy_units = 城市区域_敌方部队数量(city, 运输可行条件_基准敌部队距离);
				int enemy_troops = 城市区域_敌军死守(city, 运输可行条件_基准敌部队距离);
				if (enemy_units >= 运输可行条件_基准敌部队数 and enemy_troops >= 运输可行条件_基准敌部队兵力)
					return false;
			}

			// 设置条件：如果运输队触发的城市的当前兵力与最大兵力的比例低于基准值，则排除
			int city_troops = int(city.troops);
			int city_max_troops = int(city.max_troops);
			if (运输可行条件_兵力条件_应用[controller_index])
			{
				/// 注意：在除法计算时，有可能存在分母为0的情况（兵力为0），需注意避免分母为0的情况
				if (city_troops < city_max_troops * 运输可行条件_兵力条件_比例[controller_index] / 100)
					return false;
			}

			// 设置条件：如果运输队触发的城市的当前兵力与当前粮食的比例低于基准值，则排除
			int city_food = int(city.food);
			if (运输可行条件_兵量条件_应用[controller_index])
			{
				/// 注意：在除法计算时，有可能存在分母为0的情况（兵力为0），需注意避免分母为0的情况
				if (city_food < city_troops * 运输可行条件_兵量条件_比例[controller_index] / 100)
					return false;
			}

			return true;
		}

		// 在运输部队出发的城市接壤的自势力城市中搜寻可运输的候选城市运输부대가 출진할 도시의 자세력 인접도시 중 运输받을 후보도시를 검색
		array<pk::city @> 搜索城市_候选(pk::city @city, int controller_index)
		{
			array<pk::city @> neighbor_city_arr(0);
			for (int dir_index = 0; dir_index < 6; dir_index++)
			{
				pk::city @neighbor_city = pk::get_city(city.neighbor[dir_index]);
				if (!pk::is_alive(neighbor_city))
					continue;
				if (neighbor_city.get_force_id() != city.get_force_id())
					continue;

				if (!运输必要条件是否满足(city, neighbor_city, controller_index))
					continue;

				neighbor_city_arr.insertLast(neighbor_city);
			}

			return neighbor_city_arr;
		}

		// 确认接收运输的城市条件
		bool 运输必要条件是否满足(pk::city @city, pk::city @neighbor_city, int controller_index)
		{
			// 基本条件：如果接收运输的城市是后方城市（在城市距离2以内没有敌方城市），则排除
			int neighbor_city_status = get_city_status(neighbor_city);
			if (neighbor_city_status == 城市状态_后方)
				return false;

			// 基本条件：如果运输部队出发的城市是边界城市，且接收运输的城市是前线城市，则排除
			int city_status = get_city_status(city);
			if (city_status == 城市状态_边界 and neighbor_city_status == 城市状态_前线)
				return false;

			// 基本条件：如果已经存在前往接收运输的运输部队，则排除
			if (是否存在特定城市目标的出发运输部队(neighbor_city))
				return false;

			// 设置条件：如果接收运输的城市周围一定距离范围内存在一定数量的敌方部队和敌方兵力，则排除
			if (运输需求条件_敌部队条件_应用[controller_index])
			{
				int enemy_units = 城市区域_敌方部队数量(neighbor_city, 运输需求条件_基准敌部队距离);
				int enemy_troops = 城市区域_敌军死守(neighbor_city, 运输需求条件_基准敌部队距离);
				if (enemy_units >= 运输需求条件_基准敌部队数 and enemy_troops >= 运输需求条件_基准敌部队兵力)
					return false;
			}

			// 设置条件：如果接收运输的城市当前兵力与最大兵力的比例超过设定值，则排除
			int neighbor_city_troops = int(neighbor_city.troops);
			int neighbor_city_max_troops = int(neighbor_city.max_troops);
			if (运输需求条件_兵力条件1_应用[controller_index])
			{
				/// 注意：当兵力可能为0时，除数不能为0
				if (neighbor_city_troops > neighbor_city_max_troops * 运输需求条件_兵力条件1_比例[controller_index] / 100)
					return false;
			}

			// 设置条件：如果出发城市的当前兵力与接收运输的城市的当前兵力的比例超过设定值，则排除
			int city_troops = int(city.troops);
			if (运输需求条件_兵力条件2_应用[controller_index])
			{
				/// 注意：当兵力可能为0时，除数不能为0
				if (neighbor_city_troops > city_troops * 运输需求条件_兵力条件2_比例[controller_index] / 100)
					return false;
			}

			// 设置条件：如果接收运输的城市发生或即将发生瘟疫灾害，则排除
			if (运输需求条件_瘟疫条件_应用[controller_index])
			{
				// 如果城市状态是边界城市，则检查是否应用排除
				if (neighbor_city_status == 城市状态_边界 or (!瘟疫条件_前方城市_应用排除[controller_index] and neighbor_city_status == 城市状态_前线))
				{
					// 如果发生瘟疫灾害，则排除
					if (neighbor_city.ekibyou)
						return false;

					// 如果即将发生瘟疫灾害（下一个季度），则排除
					/// 注意：只有在下一个季度发生灾害的情况下才会排除
					if (neighbor_city.next_ekibyou and next_turn_is_next_quarter())
						return false;
				}
			}

			// 设置条件：如果接收运输的城市发生或即将发生蝗灾灾害，则排除
			if (运输需求条件_蝗灾条件_应用[controller_index])
			{
				// 如果城市状态是边界城市，则检查是否应用排除
				if (neighbor_city_status == 城市状态_边界 or (!蝗灾条件_前方城市_应用排除[controller_index] and neighbor_city_status == 城市状态_前线))
				{
					// 如果发生蝗灾灾害，则排除
					if (neighbor_city.inago)
						return false;

					// 如果即将发生蝗灾灾害（下一个季度），则排除
					/// 注意：只有在下一个季度发生灾害的情况下才会排除
					if (neighbor_city.next_inago and next_turn_is_next_quarter())
						return false;
				}
			}

			// 如果城市状态是前线城市且接收运输的城市也是前线城市
			if (city_status == 城市状态_前线 and neighbor_city_status == 城市状态_前线)
			{
				// 基本条件：如果运输部队出发城市周围的敌方城市数量超过接收运输的获取城市周围敌方城市数量的两倍，则排除
				if (获取城市周围敌方城市数量(city, 1) > 获取城市周围敌方城市数量(neighbor_city, 1) * 2)
					return false;

				// 基本条件：如果运输部队出发城市周围的敌方部队兵力超过接收运输的城市邻近敌方城市士兵数量的两倍，则排除
				else if (邻近敌方城市士兵数量(city) > 邻近敌方城市士兵数量(neighbor_city) * 2)
					return false;
			}

			// 如果城市状态是边界城市且接收运输的城市也是边界城市
			if (city_status == 城市状态_边界 and neighbor_city_status == 城市状态_边界)
			{
				for (int distance = 2; distance <= 8; distance++)
				{
					// 基本条件：如果运输部队出发城市到接收运输的城市的距离范围内，运输部队出发城市周围的敌方城市数量超过接收运输的获取城市周围敌方城市数量的两倍，则排除
					if (获取城市周围敌方城市数量(city, distance) > 获取城市周围敌方城市数量(neighbor_city, distance) * 2)
						return false;
				}
			}

			return true;
		}

		/**
		@return 判断'city_a'是否比'city_b'具有更高的电力增强优先级
		*/
		// 比较运输城市之间的增强优先级
		bool 比较优先级(pk::city @city_a, pk::city @city_b)
		{
			// 城市状态：优先考虑前线状态而不是边界状态
			int a_city_status = get_city_status(city_a);
			int b_city_status = get_city_status(city_b);
			if (a_city_status != b_city_status)
				return a_city_status > b_city_status;

			// 如果城市状态都是前线状态
			if (a_city_status == 城市状态_前线 and b_city_status == 城市状态_前线)
			{
				// 相邻敌对城市数量：数量越多，优先级越高
				int a_around_enenmy_cities = 获取城市周围敌方城市数量(city_a, 1);
				int b_around_enenmy_cities = 获取城市周围敌方城市数量(city_b, 1);
				if (a_around_enenmy_cities != b_around_enenmy_cities)
					return a_around_enenmy_cities > b_around_enenmy_cities;

				// 城市区域内敌对据点（关口和港口）的兵力：兵力越多，优先级越高
				int a_area_enemy_base_troops = 获取敌方据点兵力(city_a);
				int b_area_enemy_base_troops = 获取敌方据点兵力(city_b);
				if (a_area_enemy_base_troops != b_area_enemy_base_troops)
					return a_area_enemy_base_troops > b_area_enemy_base_troops;

				// 相邻敌对城市的士兵数量：数量越多，优先级越高
				int a_neighbor_enemy_city_troops = 邻近敌方城市士兵数量(city_a);
				int b_neighbor_enemy_city_troops = 邻近敌方城市士兵数量(city_b);
				if (a_neighbor_enemy_city_troops != b_neighbor_enemy_city_troops)
					return a_neighbor_enemy_city_troops > b_neighbor_enemy_city_troops;
			}

			// 如果城市状态都是边界状态
			if (a_city_status == 城市状态_边界 and b_city_status == 城市状态_边界)
			{
				// 周边敌对城市数量：数量越多，优先级越高（根据城市距离判断，从距离2开始比较）
				for (int distance = 2; distance <= 8; distance++)
				{
					int a_around_enenmy_cities = 获取城市周围敌方城市数量(city_a, distance);
					int b_around_enenmy_cities = 获取城市周围敌方城市数量(city_b, distance);
					if (a_around_enenmy_cities != b_around_enenmy_cities)
						return a_around_enenmy_cities > b_around_enenmy_cities;
				}
			}

			// 城市兵力：越少越高优先级
			int a_troops = city_a.troops;
			int b_troops = city_b.troops;
			return a_troops < b_troops;
		} // 运输部队出发
		/// 注意：当执行AI的基地命令时，命令的行动力将自动扣除（即，如果军团的行动力不足，则不执行命令）
		void 运输部队出发(pk::city @city, pk::building @building, pk::building @neighbor_building, int controller_index)
		{
			// 创建电脑出发命令
			pk::com_deploy_cmd_info cmd;

			// 出发基地
			@cmd.base = @building;

			// 出发部队类型
			cmd.type = 部队类型_运输;

			// 出发部队领导者
		cmd.member[0] = get_unit_leader_id(building);

			// 出发部队士兵数量
			int city_status = get_city_status(city);
			cmd.troops = get_troops_transport_volume(building, neighbor_building, city_status, controller_index);

			// 出发部队金钱数量
			cmd.gold = get_gold_transport_volume(building, neighbor_building, city_status, controller_index);

			// 出发部队粮食数量
			cmd.food = get_food_transport_volume(building, neighbor_building, city_status, controller_index);

			// 出发部队武器
			for (int weapon_id = 0; weapon_id < 武器_末; weapon_id++)
			{
				cmd.weapon_id[weapon_id] = weapon_id;
				cmd.weapon_amount[weapon_id] = get_wpn_transport_volume(building, neighbor_building, weapon_id, city_status, controller_index);
			}

			// 出发部队任务
			cmd.order = 部队任务_移动;

			// 出发部队目标坐标
			cmd.target_pos = neighbor_building.pos;

			// 执行出发命令
			int unit_id = pk::command(cmd);

			// 设置出发部队行动完成
			/// 注意：当执行AI的出发命令时，必须设置出发部队的行动完成
			if (unit_id != -1)
				pk::get_unit(unit_id).action_done = true;
		} ///	<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
		// 返回是否为常规游戏：不是决战失败、教程或任务进行中
		bool is_normal_game()
		{
			return (!pk::is_campaign() && !pk::is_mission_running());
		}

		// 返回势力的控制者索引
		int get_controller_index(pk::force @force)
		{
			return (force.is_player() ? 0 : 1);
		}

		/**
			[参考] 城市状态：根据城市之间的武装移动所需的回合数（按10天计算）

			1. 后方：在城市距离2以内没有敌方势力的城市（敌方城市在距离3开始出现）
			2. 边界：在城市距离1以内没有敌方势力的城市（敌方城市在距离2开始出现）
			3. 前线：在城市距离1以内有敌方势力的城市
		*/
		int get_city_status(pk::city @city)
		{
			if (获取城市周围敌方城市数量(city, 2) == 0)
				return 城市状态_后方;
			else if (获取城市周围敌方城市数量(city, 1) == 0)
				return 城市状态_边界;
			else
				return 城市状态_前线;
		}

		// 检查是否有足够的行动力执行命令
		/// 如果城市的内政设施中存在军事部门，则军事菜单中所有命令的行动力消耗减半
		bool ap_is_enough(pk::city @city, int needed_ap, int buff_facility_id)
		{
			if (pk::has_facility(city, buff_facility_id))
				needed_ap /= 2;
			pk::district @district = pk::get_district(city.get_district_id());
			return (int(district.ap) >= needed_ap);
		}

		// 检查下一回合是否进入下一个季度
		/// 季度的开始日期分别为1/1（春季），4/1（夏季），7/1（秋季），10/1（冬季）
		/// 因此每个季度的前一个回合分别为12/21，3/21，6/21，9/21
		bool next_turn_is_next_quarter()
		{
			return (pk::get_month() % 3 == 0 && pk::get_day() == 21);
		}

		// 返回城市周围距离城市一定距离（坐标距离）以内的敌方部队数量
		int 城市区域_敌方部队数量(pk::city @city, int distance)
		{
			int enemy_units = 0;
			array<pk::point> range_arr = pk::range(city.get_pos(), 1, distance);
			for (int pos_index = 0; pos_index < int(range_arr.length); pos_index++)
			{
				pk::point range_pos = range_arr[pos_index];
				int area_city_id = pk::get_city_id(range_pos);
				if (city.get_id() != area_city_id)
					continue;

				pk::unit @unit = pk::get_unit(range_pos);
				if (!pk::is_alive(unit))
					continue;
				if (!pk::is_enemy(city, unit))
					continue;

				enemy_units++;
			}

			return enemy_units;
		}

		// 返回城市周围距离城市一定距离（坐标距离）以内的敌方士兵数量
		int 城市区域_敌军死守(pk::city @city, int distance)
		{
			int enemy_troops = 0;
			array<pk::point> range_arr = pk::range(city.get_pos(), 1, distance);
			for (int pos_index = 0; pos_index < int(range_arr.length); pos_index++)
			{
				pk::point range_pos = range_arr[pos_index];
				int area_city_id = pk::get_city_id(range_pos);
				if (city.get_id() != area_city_id)
					continue;

				pk::unit @unit = pk::get_unit(range_pos);
				if (!pk::is_alive(unit))
					continue;
				if (!pk::is_enemy(city, unit))
					continue;

				enemy_troops += unit.troops;
			}

			return enemy_troops;
		}

		// 返回以特定城市为运输目标的城市势力中是否存在运输部队
		bool 是否存在特定城市目标的出发运输部队(pk::city @city)
		{
			for (int unit_id = 0; unit_id < 部队_末; unit_id++)
			{
				pk::unit @unit = pk::get_unit(unit_id);
				if (!pk::is_alive(unit))
					continue;

				// 如果部队类型不是运输部队，则排除
				if (unit.type != 部队类型_运输)
					continue;

				// 如果部队任务不是移动，则排除
				if (unit.order != 部队任务_移动)
					continue;

				// 如果部队势力与目标城市的势力不一致，则排除
				if (unit.get_force_id() != city.get_force_id())
					continue;

				// 如果部队的目标坐标不是目标城市的坐标，则排除
				if (unit.target_pos != city.get_pos())
					continue;

				return true;
			}

			return false;
		}

		// 返回距离城市一定距离（城市距离，以移动回合数计算）以内的敌方城市数量
		int 获取城市周围敌方城市数量(pk::city @city, int distance)
		{
			int enemy_cities = 0;
			for (int city_id = 0; city_id < 城市_末; city_id++)
			{
				pk::city @enemy_city = pk::get_city(city_id);
				if (!pk::is_alive(enemy_city))
					continue;

				// 排除搜索基准城市
				if (city.get_id() == city_id)
					continue;

				// 如果搜索基准城市和目标城市不是敌对关系，则排除
				if (!pk::is_enemy(city, enemy_city))
					continue;

				// 如果城市之间的距离超过设定的距离，则排除
				int city_distance = pk::get_city_distance(city.get_id(), city_id);
				if (city_distance > distance)
					continue;

				enemy_cities++;
			}

			return enemy_cities;
		}
		// 检查邻近敌方城市的士兵数量
		/// 注意：城市距离为2（非相邻城市），但实际上存在距离较近，可以攻击的城市
		/// 注意：城市距离为1（相邻城市），但实际上存在距离较远，难以攻击的城市（
		int 邻近敌方城市士兵数量(pk::city @city)
		{
			int enemy_troops = 0;
			for (int dir_index = 0; dir_index < 6; dir_index++)
			{
				pk::city @neighbor_city = pk::get_city(city.neighbor[dir_index]);
				if (!pk::is_alive(neighbor_city))
					continue;
				if (!pk::is_enemy(city, neighbor_city))
					continue;

				enemy_troops += int(neighbor_city.troops);
			}

			return enemy_troops;
		}

		// 获取城市区域的敌方据点兵力

		int 获取敌方据点兵力(pk::city @city)
		{
			int enemy_troops = 0;
			for (int i = 0; i < 5; i++)
			{
				int building_id = city.gate[i];
				if (building_id == -1)
					continue;

				pk::building @building = pk::get_building(building_id);
				if (!pk::is_enemy(city, building))
					continue;

				int building_troops = pk::get_troops(building);
				enemy_troops += building_troops;
			}

			return enemy_troops;
		}

		// 运输部队主将决定（候选主将武装排序）
		int get_unit_leader_id(pk::building @building)
		{
			array<pk::person @> person_arr = pk::list_to_array(pk::get_idle_person_list(building));
			person_arr.sort(function(a, b) {
				// 优先级1 - 武装特技：具有运输特技的人员优先
				if (运输部队领导_运输特技_反映)
				{
					bool a_has_skill = ch::has_skill(a, 特技_搬运);
					bool b_has_skill = ch::has_skill(b, 特技_搬运);
					if (a_has_skill and !b_has_skill)
						return true;
					if (!a_has_skill and b_has_skill)
						return false;
				}

				// 优先级2 - 特定能力：能力越高，优先级越高
				int a_stat = a.stat[运输部队领导_应用能力];
				int b_stat = b.stat[运输部队领导_应用能力];
				if (a_stat != b_stat)
					return a_stat > b_stat;

				// 优先级3 - 义理：越高，优先级越高
				int a_giri = a.giri;
				int b_giri = b.giri;
				return a_giri > b_giri;
			});

			// 设置条件：只选择忠诚度达到标准值以上的候选主将人员
			int leader_id = -1;
			for (int person_index = 0; person_index < int(person_arr.length); person_index++)
			{
				pk::person @leader = person_arr[person_index];
				if (leader.loyalty < 运输部队_领导候选_标准忠诚度)
					continue;

				leader_id = leader.get_id();

				/// 注意：如果不在此处终止for循环，则可能选择符合忠诚度标准的次要候选主将人员
				break;
			}

			return leader_id;
		}

		// 金运输量决定
		int get_gold_transport_volume(pk::building @building, pk::building @neighbor_building, int city_status, int controller_index)
		{
			// 基本条件：现有运输部队的金最大运输量
			int gold = 100000;

			// 基本条件：接收运输的城市金库存量检查（检查是否达到最大库存）
			gold = pk::min(gold, pk::get_max_gold(neighbor_building) - pk::get_gold(neighbor_building));

			// 设置条件：检查运输部队出发城市的金库存最低保持量
			array<int> 最低保持量_金 = (city_status == 城市状态_前线) ? 最低维持量_金 : 最低维持量_边界_金;
			gold = pk::min(gold, pk::max(0, pk::get_gold(building) - 最低保持量_金[controller_index]));

			// 设置条件：检查运输部队出发城市的金库存中运输比例
			gold = pk::min(gold, pk::get_gold(building) * 运输比例_金[controller_index] / 100);

			return gold;
		}

		// 兵粮运输量决定
		int get_food_transport_volume(pk::building @building, pk::building @neighbor_building, int city_status, int controller_index)
		{
			// 基本条件：现有运输部队的兵粮最大运输量
			int food = 500000;

			// 基本条件：接收运输的城市兵粮库存量检查（检查是否达到最大库存）
			food = pk::min(food, pk::get_max_food(neighbor_building) - pk::get_food(neighbor_building));

			// 设置条件：检查运输部队出发城市的兵粮库存最低保持量
			array<int> 最低保持量_兵粮 = (city_status == 城市状态_前线) ? 最低维持量_兵粮 : 最低维持量_边界_兵粮;
			food = pk::min(food, pk::max(0, pk::get_food(building) - 最低保持量_兵粮[controller_index]));

			// 设置条件：检查运输部队出发城市的兵粮库存中运输比例
			food = pk::min(food, pk::get_food(building) * 运输比例_兵粮[controller_index] / 100);

			return food;
		}

		// 兵力运输量决定
		int get_troops_transport_volume(pk::building @building, pk::building @neighbor_building, int city_status, int controller_index)
		{
			// 基本条件：现有运输部队的兵力最大运输量
			int troops = 60000;

			// 基本条件：接收运输的城市兵力库存量检查（检查是否达到最大库存）
			troops = pk::min(troops, pk::get_max_troops(neighbor_building) - pk::get_troops(neighbor_building));

			// 设置条件：检查运输部队出发城市的兵力库存最低保持量
			array<int> 最低保持量_兵力 = (city_status == 城市状态_前线) ? 最低维持量_兵力 : 最低维持量_边界_兵力;
			troops = pk::min(troops, pk::max(0, pk::get_troops(building) - 最低保持量_兵力[controller_index]));

			// 设置条件：检查运输部队出发城市的兵力库存中运输比例
			troops = pk::min(troops, pk::get_troops(building) * 运输比例_兵力[controller_index] / 100);

			return troops;
		}

		// 武器运输量决定
		int get_wpn_transport_volume(pk::building @building, pk::building @neighbor_building, int weapon_id, int city_status, int controller_index)
		{
			// 基本条件：现有运输部队的武器最大运输量
			int wpn_amount = (weapon_id < 兵器_冲车) ? 100000 : 100;

			// 基本条件：接收运输的城市武器库存量检查（检查是否达到最大库存）
			wpn_amount = pk::min(wpn_amount, pk::get_max_weapon_amount(neighbor_building, weapon_id) - pk::get_weapon_amount(neighbor_building, weapon_id));

			// 设置条件：检查运输部队出发城市的武器库存最低保持量
			array<int> 最低保持量_武器(0);
			if (weapon_id < 兵器_冲车)
				最低保持量_武器 = (city_status == 城市状态_前线) ? 最低维持量_兵装 : 最低维持量_边界_兵装;
			else if (weapon_id < 兵器_走舸)
				最低保持量_武器 = (city_status == 城市状态_前线) ? 最低维持量_攻具 : 最低维持量_边界_攻具;
			else
				最低保持量_武器 = (city_status == 城市状态_前线) ? 最低维持量_船 : 最低维持量_边界_船;
			wpn_amount = pk::min(wpn_amount, pk::max(0, pk::get_weapon_amount(building, weapon_id) - 最低保持量_武器[controller_index]));

			// 设置条件：检查运输部队出发城市的武器库存中运输比例
			int 运输比例_武器 = 0;
			if (weapon_id < 兵器_冲车)
				运输比例_武器 = 运输比例_兵装[controller_index];
			else if (weapon_id < 兵器_走舸)
				运输比例_武器 = 运输比例_攻具[controller_index];
			else
				运输比例_武器 = 运输比例_船[controller_index];
			wpn_amount = pk::min(wpn_amount, pk::get_weapon_amount(building, weapon_id) * 运输比例_武器 / 100);

			return wpn_amount;
		}

		///	<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

	}

	Main main;
}